﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GcmpModel.h"

namespace gcmp
{
    class IDocument;
    class IEndOfTransactionProcessor;
    class ITransactionErrorProcessor;
    class ITransactionError;

    /// \brief UserTransactionUtils
    ///
    /// 用户事务工具。目前只提供全局事务的关闭、打开功能。
    class GCMP_MODEL_EXPORT UserTransactionUtils
    {
    public:
        /// \brief 开启或关闭事务备份
        ///
        /// 建议只在对性能有较高要求时关闭事务，并且关闭后及时开启。
        /// 否则失去框架对Elements修改的原子性保证、事务的撤消以及重做的支持。
        /// 并且平台的部分内建命令是基于事务的备份功能实现的，在用户关闭事务备份期间如有使用到，虽然平台有措施，但不保证完全有效
        ///
        /// 平台默认事务备份处于开启状态，重复开启没有效果，返回true。
        /// \param [in] pDocument 文档指针
        /// \param [in] enableOrDisable true开启，flase关闭
        /// \param [out] errorMessage 开启失败的错误信息
        /// \return bool 是否开启或关闭备份成功
        static bool EnableOrDisableBackup(IDocument * pDocument, bool enableOrDisable, std::wstring & errorMessage);

        /// \brief 查询事务是否开启备份
        ///
        /// \param [in] pDocument 文档指针
        /// \return bool 事务是否开启
        static bool IsBackupEnabled(IDocument * pDocument);

        /// \brief 开启或关闭事务备份文件的压缩，默认是开启的
        ///
        /// \param [in] enableOrDisable true开启，flase关闭
        /// \return bool 返回设置前的状态
        static bool EnableOrDisableCompressUndoFile(bool enableOrDisable);

        /// \brief 在更新文档之前添加事务结束处理器
        /// \param pDocument 待更新的文档
        /// \param opProcessor 添加的处理器
        /// \param withChangedElements true：调用ProcessWithChangedElements处理，false：调用Process处理.
        /// 即：继承自IEndOfTransactionProcessorWithChangedElements的需要将此标识位设置为true，否则则设置为false
        /// \return bool true 添加成功， false添加失败
        static bool AddEndOfProcessorBeforeRegenerateAll(IDocument* pDocument, OwnerPtr<IEndOfTransactionProcessor> opProcessor, bool withChangedElements = false);

        /// \brief 在更新文档之后添加事务结束处理器
        /// \param pDocument 待更新的文档
        /// \param opProcessor 添加的处理器
        /// \param withChangedElements true：调用ProcessWithChangedElements处理，false：调用Process处理
        /// \return bool true 添加成功， false添加失败
        static bool AddEndOfProcessorAfterRegenerateAll(IDocument* pDocument, OwnerPtr<IEndOfTransactionProcessor> opProcessor, bool withChangedElements = false);

        /// \brief 删除指定的事务结束处理器
        /// \param pDocument  处理器所属的文档对象
        /// \param id    处理器ID
        /// \return bool true 删除成功， false删除失败
        static bool DeleteEndOfProcessor(IDocument* pDocument, Int64 id);

        /// \brief 上传事务错误
        /// 上传的事务错误会进行累加，并不会马上处理，在事务Commit之前，交给事务错误处理器去处理
        /// \param pDocument 文档指针
        /// \param opTransactionError 要上传的错误对象
        /// \return bool true 上传成功， false上传失败
        static bool PostTransactionError(IDocument* pDocument, OwnerPtr<ITransactionError> opTransactionError);

        /// \brief 根据Id删除事务错误
        /// 事务错误被处理以后，会删除对应的事务错误，在事务Commit之前，事务错误处理器就不会处理该错误
        /// \param pDocument 文档指针
        /// \param Id 要删除的错误对象Id
        /// \return bool true 删除成功， false删除失败
        static bool RemoveTransactionErrorById(IDocument* pDocument, Int64 Id);

        /// \brief 根据Id获取事务错误
        /// \param pDocument 文档指针
        /// \param Id 错误对象Id
        /// \return ITransactionError* 事务错误指针
        static const ITransactionError* GetTransactionErrorById(IDocument* pDocument, Int64 Id);

        /// \brief 删除所有事务错误
        /// \param pDocument 文档指针
        /// \return bool true 删除成功， false删除失败
        static bool ClearAllTransactionErrors(IDocument* pDocument);

        /// \brief 设置事务错误处理器
        /// 每个文档一份，gcmp的UI层会设置默认的事务错误处理器，设置后会替换平台的
        /// 在事务Commit之前，将会检查当前是否存在错误(PostTransactionError上传的事物错误)， 并将所有的错误交由该处理器处理
        ///
        /// \param pDocument 文档指针
        /// \param opTransactionErrorProcessor 待设置的事务处理器对象
        /// \return bool true设置成功， false设置失败
        static bool SetTransactionErrorProcessor(IDocument * pDocument, OwnerPtr<ITransactionErrorProcessor> opTransactionErrorProcessor);

        /// \brief 设置事务记录或者比较回调，在事务提交，UnDo、ReDo后触发
        /// \param callback 新设置的记录或者比较回调函数
        /// \return 旧的事务记录或比较回调
        static std::function<void(const std::wstring&)> SetLogOrCompareCallback(std::function<void(const std::wstring&)> callback);

        /// \brief 获取文档中上一个可撤销的事务编号。如不存在，返回-1
        /// \param pDocument 文档指针
        /// \return 返回事务编号
        static int32_t GetPreviousUndoableTransactionId(const IDocument* pDocument);

        /// \brief 是否指定的事务批量通知修改的
        /// \param pDocument 文档指针
        /// \param id 事务编号
        /// \return 是-true;否-false
        static bool ShouldTransactionNotifyChangesInBatch(const IDocument* pDocument, int32_t id);
    };
}

